package com.yuan.gather.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
import java.io.IOException;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;

/**
 * 采集项的详情
 *
 * @author zhaoff
 */
@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class GatherDetail implements Cloneable, Serializable {

    private static final long serialVersionUID = 2988046202911457340L;

    /**
     * 巡检项的名字
     */
    @XmlAttribute
    private String name;

    /**
     * 巡检项显示的名字
     */
    @XmlAttribute
    private String display;

    /**
     * 巡检项显示的英文名字
     */
    @XmlAttribute(name = "display_en")
    private String displayEn;

    /**
     * 预巡检的名字
     */
    @XmlAttribute
    private String require;

    /**
     * 成立的条件
     */
    @XmlAttribute(name = "if")
    private String ifParam;

    /**
     * geb巡检指定的driver
     */
    @XmlAttribute
    private String driver;

    /**
     * 是否是irf巡检
     */
    @XmlAttribute(name = "irf")
    private boolean irf;

    /**
     * 任务超时
     */
    @XmlAttribute
    private Integer tto;

    /**
     * 失败后重试的次数
     */
    @XmlAttribute
    private Integer retry;

    /**
     * 重试的条件
     */
    @XmlAttribute
    private String retrycondition;

    /**
     * 巡检指令
     */
    private GatherDetailCommands commands;

    /**
     * 输出项
     */
    private List<GatherDetailOutput> output;

    /**
     * 描述信息
     */
    private String description;

    /**
     * 规则
     */
    private List<GatherDetailRule> rule;

    /**
     * 影响度的定义
     */
    private Integer degree;

    /**
     * 单位的定义
     */
    private String units;

    /**
     * 用于关联第三方数据源的指标key
     */
    @XmlAttribute
    private String relkey;

    /**
     * 用于关联第三方数据源的监控类型
     */
    @XmlAttribute
    private String reltype;

    /**
     * 优先级
     */
    @XmlAttribute
    Integer priority = Integer.MAX_VALUE;

    /**
     * 所在的组
     */
    @XmlTransient
    @JsonIgnore
    private GatherGroup parentGroup;

    /**
     * 是否禁止append辅助信息 1：禁止，0：不禁止
     */
    @XmlAttribute
    private Integer disableAppend;

    /**
     * 临时变量标识此配置是 文件：0，巡检模板：1，设备配置：2 巡检的时候设备优先
     */
    @XmlTransient
    private Integer confLevel = 0;

    /**
     * 不进行基线检查  1：不检查，不采集 2：不检查，采集
     */
    @XmlAttribute
    private String nocheck;

    /**
     * 漏洞筛查页面是否展示  值为1 则不展示。默认不配置。
     */
    @XmlAttribute
    private String bugRule;

    /**
     * 保存到arangodb collection中的键， 值的格式为{dkey:["XX1", "XX2",..., "XXn"]}, 前端使用dkey数组中的内容作为待选项
     */
    @XmlAttribute
    private String dkey;

    /**
     * 采集类型 0：实时项  1：耗时项 2：不常变化项
     */
    @XmlAttribute
    private Integer collectType;

    /**
     * 类与对象映射对象
     */
    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 获取FullQualifiedName
     *
     * @return 完整的名字
     */
    public String itemKey() {
        return parentGroup.itemKey() + "." + this.getName();
    }

    /**
     * 获取显示的名字
     *
     * @return 显示的名字
     */
    public String groupDisplayName() {
        return parentGroup.getDisplay();
    }

    @XmlTransient
    @JsonIgnore
    public GatherGroup getAncestorGroup() {
        return parentGroup == null ? null : parentGroup.getParentGroup();
    }

    public GatherGroup getParentGroup() {
        return parentGroup;
    }

    public void setParentGroup(GatherGroup parentGroup) {
        this.parentGroup = parentGroup;
    }

    @Override
    public GatherDetail clone() throws CloneNotSupportedException {
        GatherDetail ret = (GatherDetail) super.clone();
        if (commands != null) {
            ret.commands = commands.clone();
        }
        if (output != null) {
            ret.output = new LinkedList<>();
            for (GatherDetailOutput item : output) {
                ret.output.add(item.clone());
            }
        }
        if (rule != null) {
            ret.rule = new LinkedList<>();
            for (GatherDetailRule r : rule) {
                ret.rule.add(r.clone());
            }
        }
        //实体克隆
        List<GatherDetailOutput> copyBlchkDetailOutput;
        GatherGroup parentGroup;
        try {
            parentGroup = mapper.readValue(mapper.writeValueAsBytes(this.parentGroup), GatherGroup.class);
            ret.setParentGroup(parentGroup);

            JavaType javaTypeBlchkDetailOutputl =
                    mapper.getTypeFactory().constructParametricType(List.class, GatherDetailOutput.class);
            copyBlchkDetailOutput = mapper.readValue(mapper.writeValueAsBytes(this.commands),
                    javaTypeBlchkDetailOutputl);
            ret.setOutput(copyBlchkDetailOutput);

        } catch (IOException e) {
            //log.warn(null, e);
        }
        return ret;
    }

    /**
     * 判断该indicator是否是不采集的项
     *
     * @return true:不采集   false:采集
     */
    public boolean noGather() {
        return "1".equals(nocheck) || "3".equals(nocheck);
    }

    /**
     * 判断该indicator是否是不做基线检查的项
     *
     * @return true:不检查   false:检查
     */
    public boolean noBlCheck() {
        return "1".equals(nocheck) || "2".equals(nocheck);
    }

}
